package main.leetcode.clockin.September;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 39. 组合总和
 *
 * <p>给定一个无重复元素的数组 candidates 和一个目标数 target ，找出 candidates 中所有可以使数字和为 target 的组合。
 *
 * <p>candidates 中的数字可以无限制重复被选取。
 *
 * <p>说明：所有数字（包括 target）都是正整数。 解集不能包含重复的组合。
 *
 * <p>示例 1：输入：candidates = [2,3,6,7], target = 7, 所求解集为： [ [7], [2,2,3] ]
 *
 * <p>示例 2：输入：candidates = [2,3,5], target = 8, 所求解集为： [ [2,2,2,2], [2,3,3], [3,5] ]
 *
 * <p>提示：1 <= candidates.length <= 30 1 <= candidates[i] <= 200 candidate 中的每个元素都是独一无二的。 1 <= target
 * <= 500
 */
public class day9 {
    private List<List<Integer>> res;

    public static void main(String[] args) {
        System.out.println(new day9().combinationSum(new int[] {2, 3, 5}, 8));
    }

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        res = new ArrayList<>();
        if (candidates == null || candidates.length < 1) {
            return res;
        }
        Arrays.sort(candidates);
        backTrack(candidates, target, 0, 0, new ArrayList<>());
        return res;
    }

    private void backTrack(int[] candidates, int tar, int cur, int index, List<Integer> list) {
        if (cur == tar) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = index; i < candidates.length; ++i) {
            int num = candidates[i];
            if (cur + num > tar) {
                break;
            }
            list.add(num);
            backTrack(candidates, tar, cur + num, i, list);
            list.remove(list.size() - 1);
        }
    }
}
